using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using ActiproSoftware.SyntaxEditor.ParserGenerator;

namespace ActiproSoftware.SyntaxEditor.Addons.Simple {

	/// <summary>
	/// Represents a <c>Simple</c> recursive descent lexical parser implementation.
	/// </summary>
	internal class SimpleRecursiveDescentLexicalParser : MergableRecursiveDescentLexicalParser {

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// OBJECT
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Initializes a new instance of the <c>SimpleRecursiveDescentLexicalParser</c> class.
		/// </summary>
		/// <param name="language">The <see cref="SimpleSyntaxLanguage"/> to use.</param>
		/// <param name="manager">The <see cref="MergableLexicalParserManager"/> to use for coordinating merged languages.</param>
		public SimpleRecursiveDescentLexicalParser(SimpleSyntaxLanguage language, MergableLexicalParserManager manager) : base(language, manager) {}
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// PUBLIC PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Returns the next <see cref="IToken"/> and seeks past it.
		/// </summary>
		/// <returns>The next <see cref="IToken"/>.</returns>
		protected override IToken GetNextTokenCore() {
			IToken token = null;
			int startOffset = this.TextBufferReader.Offset;

			while (!this.IsAtEnd) {
				// Get the next token
				token = this.Manager.GetNextToken();

				// Update whether there is non-whitespace since the last line start
				if (token.LexicalState == this.Language.DefaultLexicalState) {
					switch (token.ID) {
						case SimpleTokenID.LineTerminator:
						case SimpleTokenID.MultiLineComment:
						case SimpleTokenID.SingleLineComment:
						case SimpleTokenID.Whitespace:
							// Consume non-significant token
							break;
						default:
							// Return the significant token
							return token;
					}
				}
				else if (token.HasFlag(LexicalParseFlags.LanguageStart)) {
					// Return the significant token (which is in a different language)
					return token;
				}

				// Advance the start offset
				startOffset = this.TextBufferReader.Offset;
			}

			// Return an end of document token
			if (this.Token != null)
				return this.Language.CreateDocumentEndToken(startOffset, this.Token.LexicalState);
			else
				return this.Language.CreateDocumentEndToken(startOffset, this.Language.DefaultLexicalState);
		}

	}
}
